﻿// This code is released under the BSD license.
namespace PugLib
{
    using System;
    using System.Diagnostics.CodeAnalysis;
    using System.Globalization;
    using System.IO;
    using System.Text;
    using Extensions.Collections;

    //safe conversion class
    public static class SafeConvert
    {
        public static int ToInt32FromHex(object value)
        {
            if (value == null || (value == DBNull.Value))
            {
                return default(int);
            }
            return Int32.Parse(value.ToString(), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
        }

        public static short ToInt16(object value)
        {
            if ((value == null) || (value == DBNull.Value) || (value.ToString().Length == 0))
            {
                return default(short);
            }

            Int16 rtn;
            if (Int16.TryParse(value.ToString(), NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out rtn))
            {
                return rtn;
            }
            return default(Int16);
        }

        public static Int32 ToInt32(Object value)
        {
            if (value == null || value == DBNull.Value || String.IsNullOrEmpty(value.ToString()))
            {
                return default(Int32);
            }

            Int32 rtn;
            if (Int32.TryParse(value.ToString(), NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out rtn))
            {
                return rtn;
            }
            return default(Int32);
        }

        public static Int64 ToInt64(Object value)
        {
            if (value == null || (value == DBNull.Value))
            {
                return default(Int64);
            }

            Int64 rtn;
            if (Int64.TryParse(value.ToString(), NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out rtn))
            {
                return rtn;
            }
            return default(Int64);
        }

        public static Double ToDouble(Object value)
        {
            if (value == null || (value == DBNull.Value) || String.IsNullOrEmpty(value.ToString()))
            {
                return default(Double);
            }

            Double rtn;
            if (Double.TryParse(value.ToString(), NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out rtn))
            {
                return rtn;
            }
            return default(Double);
        }

        public static Decimal ToDecimal(object value)
        {
            if (value == null || (value == DBNull.Value))
            {
                return default(Decimal);
            }

            Decimal rtn;
            if (Decimal.TryParse(value.ToString(), NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out rtn))
            {
                return rtn;
            }
            return default(Decimal);
        }


        public static string ToString(object value)
        {
            if (value == null || (value == DBNull.Value))
            {
                return string.Empty;
            }

            return value.ToString();
        }

        public static DateTime ToDateTime(object value)
        {
            if (value == null || (value == DBNull.Value))
            {
                return DateTime.MinValue;
            }

            return Convert.ToDateTime(value, CultureInfo.InvariantCulture);
        }

        public static string ToShortDateTimeString(object value)
        {
            return ToDateTime(value).ToShortDateString();
        }

        public static string ToLongDateTimeString(object value)
        {
            return ToDateTime(value).ToLongDateString();
        }

        public static string ToGeneralDateString(object value)
        {
            return ToDateTime(value).ToString("G", CultureInfo.InvariantCulture);
        }

        public static T GetAs<T>(object value)
        {
            if (value == null || (value == DBNull.Value))
            {
                return Activator.CreateInstance<T>();
            }
            try
            {
                return (T)Convert.ChangeType(value, typeof(T), CultureInfo.InvariantCulture);
            }
            catch
            {
                return Activator.CreateInstance<T>();
            }
        }

        public static Boolean ToBoolean(object value)
        {
            return ToBoolean(value, default(Boolean));
        }


        public static bool ToBoolean(object value, bool def)
        {
            if (value == null || (value == DBNull.Value))
            {
                return default(Boolean);
            }

            Boolean rtn;
            if (Boolean.TryParse(value.ToString(), out rtn))
            {
                return rtn;
            }
            return def;
        }

        public static int ToInt32(object input, int def)
        {
            if (StringUtilities.IsNumeric(input))
            {
                return Convert.ToInt32(input, CultureInfo.InvariantCulture);
            }
            return def;
        }


        public static decimal ToDecimal(object input, decimal def)
        {
            if (StringUtilities.IsNumeric(input))
            {
                return Convert.ToDecimal(input, CultureInfo.InvariantCulture);
            }
            return def;
        }


        public static double ToDouble(object input, double def)
        {
            if (StringUtilities.IsNumeric(input))
            {
                return Convert.ToDouble(input, CultureInfo.InvariantCulture);
            }
            return def;
        }


        public static string ToHexString(byte[] data)
        {
            if (data == null || data.Length == 0)
            {
                return string.Empty;
            }
            StringBuilder sb = new StringBuilder(data.Length * 2);
            data.ForEach(b => sb.AppendFormat("{0:x2}", b));
            return sb.ToString();
        }

        public static MemoryStream ToStream(string input)
        {
            return new MemoryStream(Encoding.ASCII.GetBytes(input.ToCharArray()));
        }

        public static string ToString<T>(T obj)
        {
            if (obj == null || obj is DBNull)
            {
                return string.Empty;
            }

            return Convert.ToString(obj, CultureInfo.InvariantCulture);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter", Justification = "Generic return type")]
        public static T ToEnum<T>(object value)
        {
            if (value is DBNull)
            {
                return default(T);
            }

            return (T)Enum.Parse(typeof(T), value.ToString(), true);
        }

        /// <summary>
        /// Converts the provided object to its enum value if defined.  Otherwise, returns the provided default value
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static T ToEnum<T>(object value, T defaultValue)
        {
            return value == null ? defaultValue : ToEnum(value.ToString(), defaultValue);
        }

        /// <summary>
        /// Converts the provided object to its enum value if defined.  Otherwise, returns the provided default value
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static T ToEnum<T>(string value, T defaultValue)
        {
            if (string.IsNullOrEmpty(value))
            {
                return defaultValue;
            }

            Type type = defaultValue.GetType();

            if (Enum.IsDefined(type, value))
            {
                return (T)Enum.Parse(type, value, true);
            }

            int val;
            if (int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out val))
            {
                if (Enum.IsDefined(type, val))
                {
                    return (T)Enum.Parse(type, value, true);
                }
            }

            return defaultValue;
        }


        public static int MinutesToMilliseconds(int minutes)
        {
            TimeSpan timespan = new TimeSpan(0, minutes, 0);
            return ToInt32(timespan.TotalMilliseconds);
        }


    }
}